/**
 * File name:      PropertyCopyUtil.java
 * Date:           2013-3-25
 * Description:    // 用于详细说明此程序文件完成的主要功
 *                 // 能与其他模块或函数的接口，输出值、
 *                 // 取值范围、含义及参数间的关系
 * Modify History:     Date             Programmer       Notes
 *                    ---------        ---------------  ---------
 *                    2013-3-25            伍冲                              Initial
 **********************************************************************/
package com.wy.component.dataConvert;

import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Created on 2013-3-25
 * <p>Title:      [属性拷贝工具]</p>
 * <p>Description: [属性拷贝工具]</p>
 * @version        1.0
 */
public class PropertyCopyUtil {
	/**
	 * 
	 * Method Description:<br>
	 * <font color="blue">把源对象属性值 拷贝至 目标对象 相匹配的 属性中去，源对象和目标对象可以是JavaBean、Map（HashMap、Hashtable、Properties等）类型。</font><br>
	 * <b>适用范围：</b><br>1，JavaBean对象属性值拷贝至Map（HashMap、Hashtable、Properties等）类型中;<br>
	 * 		   2，JavaBean对象属性值拷贝至另一个JavaBean中; <br>
	 *  	   3，Map（HashMap、Hashtable、Properties等）类型对象属性值拷贝至一个JavaBean中;<br>
	 *         4，Map（HashMap、Hashtable、Properties等）类型对象属性值拷贝至一个Map类型对象中;<br>
	 *
	 * @param:  Object srcObject          --源对象

	 * @param:  Object targetObject       --目标对象
	 * @param:  String[] ignoreProperties --忽略拷贝的属性（如果不想拷贝某些属性，可以传入属性名称数组）
	 * 
	 * @return: target Object
	 */
  public static Object CopyProperties(Object srcObject,Object targetObject,String[] ignoreProperties){
	  if(srcObject instanceof Map){
		  if(targetObject instanceof Map){
			  Map2Map((Map)srcObject,(Map)targetObject,ignoreProperties);
		  }else{
			  Map2Bean((Map)srcObject,targetObject,ignoreProperties);
		  }
	  }else{
		  if(targetObject instanceof Map){
			  Bean2Map(srcObject,(Map)targetObject,ignoreProperties);
		  }else{
			  Bean2Bean(srcObject,targetObject,ignoreProperties);
		  }
	  }
	  
	  return targetObject;
  }
  
  /**
	 * 
	 * Method Description:把JavaBean类型对象属性值 拷贝至另一个 JavaBean对象
	 *
	 * @param:  Object orangalObject,Object targetObject
	 * @return: target Object
	 */
	private static Object Bean2Bean(Object srcObject,Object targetObject,String[] excludeProperties){
		//1，获取srcObject和targetObject对象方法集合
		Method[] srcMethods   = srcObject.getClass().getMethods();
		Method[] targetMethods= targetObject.getClass().getMethods();
		//2,使用反射机制循环获取属性值

		for(int i=0;i<srcMethods.length;i++){
			//源对象反射

			String srcMethodName  = srcMethods[i].getName();
			//跳过排除属性

			boolean isIgnore = false; 
			if(excludeProperties!=null){
				for(int k=0;k<excludeProperties.length;k++){
					if(srcMethodName.toLowerCase().endsWith(excludeProperties[k].toLowerCase())){
						isIgnore = true;
						break;
					}
				}
			}
			if(isIgnore){
				continue;
			}
			try{
				if(srcMethodName.startsWith("get")&&!srcMethodName.equals("getClass")){
					Object[] getParamValue= new Object[]{};
					Object returnValue = srcMethods[i].invoke(srcObject, getParamValue);
					for(int j=0;j<targetMethods.length;j++){
						String targetMethodName = targetMethods[j].getName();
						if(targetMethodName.startsWith("set")){
							if(srcMethodName.substring(3).equals(targetMethodName.substring(3))){
								if(srcMethods[i].getReturnType().getName().equals(targetMethods[j].getParameterTypes()[0].getName())){
									Object[] targetMethodParamValue= new Object[]{returnValue};
									targetMethods[j].invoke(targetObject,targetMethodParamValue);
								}else{
									String targetMethodParamName = targetMethods[j].getParameterTypes()[0].getName();
									String targetMethodParam = String.valueOf(returnValue);
									if("int".equals(targetMethodParamName)||"java.lang.Integer".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{Integer.valueOf(targetMethodParam)});
									}
									if("long".equals(targetMethodParamName)||"java.lang.Long".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{Long.valueOf(targetMethodParam)});
									}
									if("double".equals(targetMethodParamName)||"java.lang.Double".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{Double.valueOf(targetMethodParam)});
									}
									if("float".equals(targetMethodParamName)||"java.lang.Float".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{Float.valueOf(targetMethodParam)});
									}
									if("byte".equals(targetMethodParamName)||"java.lang.Byte".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{Byte.valueOf(targetMethodParam)});
									}
									if("boolean".equals(targetMethodParamName)||"java.lang.Boolean".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{Boolean.valueOf(targetMethodParam)});
									}
									if("char".equals(targetMethodParamName)||"java.lang.Character".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{(targetMethodParam)});
									}
									if("java.lang.String".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{targetMethodParam});
									}
									if("java.util.Date".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{(stringToDate(targetMethodParam))});
									}
									if("java.sql.Timestamp".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{stringToTimestamp(targetMethodParam)});
									}
									if("java.util.Calendar".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{stringToCalendar(targetMethodParam)});
									}
									if("java.sql.Date".equals(targetMethodParamName)){
										targetMethods[j].invoke(targetObject,new Object[]{stringToDate(targetMethodParam)});
									}
								}
								break;
							}
						}
					}
				}
			}catch(Exception e){			
			}
		}
		return targetObject;
	}
	
	/**
	 * 
	 * Method Description:把JavaBean类型对象属性值 拷贝至 Map对象
	 *
	 * @param:  Object orangalObject,Object targetObject
	 * @return: target Object
	 */
	private static Object Bean2Map(Object srcObject,Map targetObject,String[] excludeProperties){
		//1，获取srcObject和targetObject对象方法集合
		Method[] srcMethods   = srcObject.getClass().getMethods();
		//2,使用反射机制循环获取属性值

		for(int i=0;i<srcMethods.length;i++){
			//源对象反射

			String srcMethodName  = srcMethods[i].getName();
			//跳过排除属性

			boolean isIgnore = false; 
			if(excludeProperties!=null){
				for(int k=0;k<excludeProperties.length;k++){
					if(srcMethodName.toLowerCase().endsWith(excludeProperties[k].toLowerCase())){
						isIgnore = true;
						break;
					}
				}
			}
			if(isIgnore){
				continue;
			}
			try{
				if(srcMethodName.startsWith("get")&&!srcMethodName.equals("getClass")){
					Object[] getParamValue= new Object[]{};
					Object returnValue = srcMethods[i].invoke(srcObject, getParamValue);
					String targetMethodParamName = returnValue.getClass().getName();
					String key = srcMethodName.substring(3,4).toLowerCase()+srcMethodName.substring(4);
					if("int".equals(targetMethodParamName)){
						targetObject.put(key,Integer.valueOf(String.valueOf(returnValue)));
					}else if("long".equals(targetMethodParamName)){
						targetObject.put(key,Long.valueOf(String.valueOf(returnValue)));
					}else if("double".equals(targetMethodParamName)){
						targetObject.put(key,Double.valueOf(String.valueOf(returnValue)));
					}else if("float".equals(targetMethodParamName)){
						targetObject.put(key,Float.valueOf(String.valueOf(returnValue)));
					}else if("byte".equals(targetMethodParamName)){
						targetObject.put(key,Byte.valueOf(String.valueOf(returnValue)));
					}else if("boolean".equals(targetMethodParamName)){
						targetObject.put(key,Boolean.valueOf(String.valueOf(returnValue)));
					}else if("char".equals(targetMethodParamName)){
						targetObject.put(key,String.valueOf(returnValue));
					}else{
						targetObject.put(key,returnValue);
					}
				  }
				}catch(Exception e){			
			}
		}
		return targetObject;
	}
	
	/**
	 * 
	 * Method Description:把Map类型对象属性值 拷贝至 Map对象
	 *
	 * @param:  Object orangalObject,Object targetObject
	 * @return: target Object
	 */
	private static Object Map2Map(Map srcObject,Map targetObject,String[] excludeProperties){
		Set keys = srcObject.keySet();
		for(Iterator it=keys.iterator();it.hasNext();){
			//取值

			String key   = (String)it.next();
			Object value = srcObject.get(key);
			//跳过排除属性

			boolean isIgnore = false; 
			if(excludeProperties!=null){
				for(int k=0;k<excludeProperties.length;k++){
					if(key.equals(excludeProperties[k])){
						isIgnore = true;
						break;
					}
				}
			}
			if(isIgnore){
				continue;
			}
			//赋值

			targetObject.put(key, value);
		}
		return targetObject;
	}
	
	/**
	 * 
	 * Method Description: 把Map类型对象属性值 拷贝至 JavaBean对象
	 *
	 * @param:  Object orangalObject,Object targetObject
	 * @return: target Object
	 */
	private static Object Map2Bean(Map srcObject,Object targetObject,String[] excludeProperties){
		//1，获取srcObject对象属性

		Set fields = srcObject.keySet();
		//2,使用反射机制循环获取属性值

		for(Iterator it=fields.iterator();it.hasNext();){
			//源对象反射

			String fieldName  = (String)it.next();
			//跳过排除属性

			boolean isIgnore = false; 
			if(excludeProperties!=null){
				for(int k=0;k<excludeProperties.length;k++){
					if(fieldName.equals(excludeProperties[k])){
						isIgnore = true;
						break;
					}
				}
			}
			if(isIgnore){
				continue;
			}
			Object returnValue = srcObject.get(fieldName);
			//获取目标对象反射方法
			String setMethodName ="set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
			//判断目标方法是否存在
			Method[] targetMethods= targetObject.getClass().getMethods();
			for(int j=0;j<targetMethods.length;j++){
				if(targetMethods[j].getName().equals(setMethodName)){
					//3,目标对象set赋值

					try {
						if(returnValue instanceof Object){
							Object[] targetMethodParamValue= new Object[]{returnValue};
							targetMethods[j].invoke(targetObject,targetMethodParamValue);
						}else{
							String targetMethodParamName = targetMethods[j].getParameterTypes()[0].getName();
							String targetMethodParam = String.valueOf(returnValue);
							if("int".equals(targetMethodParamName)){
								targetMethods[j].invoke(targetObject,new Object[]{Integer.valueOf(targetMethodParam)});
							}
							if("long".equals(targetMethodParamName)){
								targetMethods[j].invoke(targetObject,new Object[]{Long.valueOf(targetMethodParam)});
							}
							if("double".equals(targetMethodParamName)){
								targetMethods[j].invoke(targetObject,new Object[]{Double.valueOf(targetMethodParam)});
							}
							if("float".equals(targetMethodParamName)){
								targetMethods[j].invoke(targetObject,new Object[]{Float.valueOf(targetMethodParam)});
							}
							if("byte".equals(targetMethodParamName)){
								targetMethods[j].invoke(targetObject,new Object[]{Byte.valueOf(targetMethodParam)});
							}
							if("boolean".equals(targetMethodParamName)){
								targetMethods[j].invoke(targetObject,new Object[]{Boolean.valueOf(targetMethodParam)});
							}
							if("char".equals(targetMethodParamName)){
								targetMethods[j].invoke(targetObject,new Object[]{(targetMethodParam)});
							}
						}
					} catch (Exception e) {
					}
					break;
				}
			}

			
		}
		return targetObject;
	}
	
	public static Date stringToDate(String str){
    	DateFormat df = null;
    	if(str == null || str.trim().length()==0)
            return null;
    	 try{
             df = new SimpleDateFormat("yyyy-MM-dd");
             return df.parse(str);
         }catch(ParseException aioe){
              return null;
         }
    }
	
	public static Calendar stringToCalendar(String str) {
    	Date date = stringToDate(str);
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	return cal;
    }
	
	public static Timestamp stringToTimestamp(String str) {
	     Timestamp sdate = null;
	      if (str != null) {
	        try {
	        	DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	        	Date dt = df.parse(str);
	        	Calendar cal = Calendar.getInstance();
	        	cal.setTime(dt);
	        	return new Timestamp(cal.getTimeInMillis());
	        }
	        catch (Exception e) {
	        }
	      }
	      return sdate;
	    }

}
